﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

namespace HostsEditor
{
    public class HostCollection : List<Host>
    {
        public HostCollection()
            : base()
        {
            GetFileName();
            Load();
        }

        private FileInfo GetFileName()
        {
            string tmpResult = (Microsoft.Win32.Registry.GetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters", "DataBasePath", @"%SystemRoot%\System32\drivers\etc")).ToString();

            if (!string.IsNullOrEmpty(tmpResult))
                tmpResult = "%SystemRoot%\\System32\\drivers\\etc\\hosts";

            tmpResult = Environment.ExpandEnvironmentVariables(tmpResult);

            fileName = new FileInfo(tmpResult);
            return fileName;
        }

        public virtual Host Add(bool Enabled, string IP, string Host, string Comment)
        {
            Host host = new Host(Enabled, IP, Host, Comment);
            Add(host);
            return host;
        }

        public virtual bool Load()
        {
            bool result = false;

            if (HostsFile.Exists)
            {
                FileStream hosts = new FileStream(HostsFile.FullName, FileMode.Open, FileAccess.Read);
                StreamReader reader = new StreamReader(hosts);

                string file = reader.ReadToEnd();
                reader.Close();

                Clear();

                MatchCollection matchs = Regex.Matches(file, Host.SearchExpression, RegexOptions.Compiled | RegexOptions.Multiline);
                foreach (Match match in matchs)
                {
                    if (match.Groups[0].Value.Trim().Length == 0)
                        continue;

                    if (match.Groups[Host.Search_TheHostRecord].Value.Trim().Length == 0)
                    {
                        Add(new Host(match.Groups[Host.Search_Comment].Value.Trim()));
                    }
                    else
                    {
                        string comment = match.Groups[Host.Search_Comment].Value.Trim();
                        Add(new Host(
                            match.Groups[Host.Search_EnabledFlag].Length == 0,
                            match.Groups[Host.Search_IPAddress].Value.Trim(),
                            match.Groups[Host.Search_HostName].Value.Trim(),
                            (comment.Length > 1) ? comment.Substring(1) : comment));
                    }
                }

                result = true;
            }

            return result;
        }

        public virtual bool Save()
        {
            bool result = false;
            bool writeProtected = false;

            // If file is write-protected, clear RO-Bit
            if ((HostsFile.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
            {
                File.SetAttributes(HostsFile.FullName, HostsFile.Attributes ^ FileAttributes.ReadOnly);
                writeProtected = true;
            }

            FileStream hosts = new FileStream(HostsFile.FullName, FileMode.Create, FileAccess.Write);
            StreamWriter writer = new StreamWriter(hosts);

            foreach (Host item in this)
                writer.WriteLine(item.ToString());

            writer.Close();
            result = true;

            // If file was write-protected at access, set RO-Bit
            if (writeProtected)
            {
                File.SetAttributes(HostsFile.FullName, HostsFile.Attributes | FileAttributes.ReadOnly);
            }

            return result;
        }

        private FileInfo fileName = null;
        public virtual FileInfo HostsFile
        {
            get { return fileName; }
        }
    }
}
